#include <sstream>
#include <ctime>
#include <chrono>
//#include <iomanip>  // for put_time

#include "mpDateUtils.h"

namespace MP{
namespace DateUtils{

////private member
//namespace{
//} //private member


/***************************************************
 * timt_t转字符串
 * *************************************************/

std::string time_to_local_date_string(const time_t& time){
    //%Y-%m-%d                      例子：2021-10-12
    return time_to_local_datetime_string(time,"%Y-%m-%d");
}

std::string time_to_local_datetime_string(const time_t& time){
    //%Y-%m-%d %H:%M:%S             例子：2021-10-12 15:23:31
    return time_to_local_datetime_string(time,"%Y-%m-%d %H:%M:%S");
}

std::string time_to_local_datetime_string(const time_t& time,
                                          const std::string& format){
    //自定义格式，可参考 https://en.cppreference.com/w/cpp/chrono/c/strftime
    char buffer[100];
    std::strftime(buffer,sizeof(buffer),format.c_str(),std::localtime(&time));
    return buffer;
}

std::string time_to_gmt_string(const time_t& time){
    //%a, %d %b %Y %H:%M:%S GMT     例子：Tue, 18 Oct 2022 12:59:29 GMT
    char buffer[30];
    std::strftime(buffer,sizeof(buffer),"%a, %d %b %Y %H:%M:%S GMT",std::gmtime(&time));
    return buffer;
}

std::string time_to_gmt_string_iso8601(const time_t& time){
    //%Y%m%dT%H%M%SZ                例子：
    char buffer[100];
    std::strftime(buffer,sizeof(buffer),"%Y%m%dT%H%M%SZ",std::gmtime(&time));
    //std::strftime(buffer,sizeof(buffer), "%Y-%m-%dT%H:%M:%S.000Z", &tm);
    return buffer;
}

/***************************************************
 * 字符串转timt_t
 * *************************************************/
bool string_to_time(const std::string& str,
                    const std::string& format,
                    time_t& time){

    if(str.empty() || format.empty()){
        return false;
    }


    // 定义时间的各个int临时变量。
    int year=1900, month=1, day=1, hour=0, minute=0, second=0;
    // 将string存储的日期时间，转换为int临时变量。
    int count = sscanf(str.c_str(), format.c_str(), &year, &month, &day, &hour, &minute, &second);

    if(count<=0){
        return false;
    }
    else{
        custom_time(time,year,month,day,hour,minute,second);
        return true;
    }
}

void custom_time(time_t& time,int year,int month,int day,int hour,int minute,int second)
{
    struct std::tm tm;                        // 定义tm结构体。
    tm.tm_year = year - 1900;                 // 年，由于tm结构体存储的是从1900年开始的时间，所以tm_year为int临时变量减去1900。
    tm.tm_mon = month - 1;                    // 月，由于tm结构体的月份存储范围为0-11，所以tm_mon为int临时变量减去1。
    tm.tm_mday = day;                         // 日。
    tm.tm_hour = hour;                        // 时。
    tm.tm_min = minute;                       // 分。
    tm.tm_sec = second;                       // 秒。
    tm.tm_isdst = 0;                          // 非夏令时。

    time = std::mktime(&tm);
}


/***************************************************
 * 获取当前时间(system_clock 系统时间)
 * *************************************************/
time_t get_now_time(){
    auto tp = std::chrono::system_clock::now();
    return std::chrono::system_clock::to_time_t(tp);
}

std::string get_now_local_date_string(){
    time_t time = get_now_time();
    return time_to_local_date_string(time);
}

std::string get_now_local_datetime_string(){
    time_t time = get_now_time();
    return time_to_local_datetime_string(time);
}

std::string get_now_local_datetime_string_withms(){
    auto now = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now());
    time_t t = std::chrono::system_clock::to_time_t(now);

    int milliSecond = now.time_since_epoch().count() % 1000;
    auto localTm = std::localtime(&t);
    char buff[32];
    int len = std::strftime(buff, 32, "%Y-%m-%d %H:%M:%S", localTm);
    std::sprintf(buff + len, ".%03u", milliSecond);
    return buff;
}

std::string get_now_local_datetime_string(const std::string& format){
    time_t time = get_now_time();
    return time_to_local_datetime_string(time,format);
}

std::string get_now_gmt_string(){
    time_t time = get_now_time();
    return time_to_gmt_string(time);
}

std::string get_now_gmt_string_iso8601(){
    time_t time = get_now_time();
    return time_to_gmt_string_iso8601(time);
}


/***************************************************
 * 时间操作
 * *************************************************/

MP_TIME_T getsec_now_from_2000(){
    time_t t_now = get_now_time();
    return getsec_time_from_2000(t_now);
}

MP_TIME_T getsec_time_from_2000(const time_t& time){
    time_t t_2000;
    custom_time(t_2000,2000,1,1);

    return time - t_2000;
}

bool is_now_before_time(int year,int month,int day,int hour, int minute,int second){
    time_t t_now = get_now_time();

    time_t t_custom;
    custom_time(t_custom,year,month,day,hour,minute,second);

    return std::difftime(t_custom,t_now) > 0;
}

void time_add_days(time_t& time,MP_TIME_T value){
    time_add_seconds(time,value*60*60*24);
}

void time_add_hours(time_t& time,MP_TIME_T value){
    time_add_seconds(time,value*60*60);
}

void time_add_minutes(time_t& time,MP_TIME_T value){
    time_add_seconds(time,value*60);
}

void time_add_seconds(time_t& time,MP_TIME_T value){
    time = time + value;
}


///**
// * @brief 转换统一的日期格式, XXXX年XX月XX日
// * @param str
// * @return
// */
//std::string dateStringFormat(const std::string & str){
//    std::string result = "";
//    try {
//        boost::gregorian::date gdt2 = boost::gregorian::from_undelimited_string(str.c_str());

//        char szTime[50] = { '\0' };
//        sprintf(szTime, "%04d年%02d月%02d日",
//                (int)gdt2.year(),
//                (int)gdt2.month(),
//                (int)gdt2.day());

//        result = szTime;
//    }
//    catch (...) {
//        // everything else
//        MPLOG_ERROR << "StringToDateformat error:" << str;
//    }

//    return result;
//}

#ifdef PLATFORM_WINDOWS

std::string filetime_to_local_datetime_string(FILETIME& ft)
{
    //参考：https://www.cnblogs.com/findumars/p/4902952.html?utm_source=debugrun&utm_medium=referral

    FILETIME localft;
    ZeroMemory(&localft, sizeof(FILETIME));
    FileTimeToLocalFileTime(&ft, &localft);

    SYSTEMTIME st;
    ZeroMemory(&st, sizeof(SYSTEMTIME));
    FileTimeToSystemTime(&localft, &st);

    char str_create_time[24] = { '\0' };
    sprintf(str_create_time, "%04d-%02d-%02d %02d:%02d:%02d",
            st.wYear,
            st.wMonth,
            st.wDay,
            st.wHour,
            st.wMinute,
            st.wSecond);
    return str_create_time;
}

#endif //PLATFORM_WINDOWS

}   //END DateUtils
}   //END MP











